package com.hibase.core.excel.service.impl;

import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.spring.SpringUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.github.pagehelper.PageInfo;
import com.hibase.core.excel.entity.MdsExcelImportConfig;
import com.hibase.core.excel.mapper.MdsExcelImportConfigMapper;
import com.hibase.core.excel.service.MdsExcelImportConfigService;
import com.hibase.core.excel.util.Validate;
import com.hibase.core.excel.vo.config.MdsExcelImportConfigSearchVO;
import com.hibase.core.excel.vo.dynamic.DynamicExcelResult;
import com.hibase.core.mybatis.service.BaseServiceImpl;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.BindingResult;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.List;

/**
 * Excel 模板配置表 Service 实现类
 *
 * @author <a href="mailto:xiongliyi@hichain.com">Ian Xiong</a>
 * @since 1.4.35-V2
 */
@Service
public class MdsExcelImportConfigServiceImpl extends BaseServiceImpl<MdsExcelImportConfigMapper, MdsExcelImportConfig> implements MdsExcelImportConfigService {

    @Override
    public PageInfo queryPage(MdsExcelImportConfigSearchVO searchVO) {
        QueryWrapper<MdsExcelImportConfig> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(MdsExcelImportConfig::getBeDeleted, Boolean.FALSE);

        if (StrUtil.isNotEmpty(searchVO.getKeyWord())) {
            queryWrapper.lambda().like(MdsExcelImportConfig::getName, searchVO.getKeyWord());
        }

        // 业务数据集ID
        if (StrUtil.isNotEmpty(searchVO.getBizDataId())) {
            queryWrapper.lambda().eq(MdsExcelImportConfig::getBizDataId, searchVO.getBizDataId());
        }

        if (StrUtil.isNotEmpty(searchVO.getName())) {
            queryWrapper.lambda().like(MdsExcelImportConfig::getName, searchVO.getName());
        }

        queryWrapper.lambda().orderByDesc(MdsExcelImportConfig::getUpdateTime);

        return super.page(searchVO, queryWrapper);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean saveImportConfig(MdsExcelImportConfig entity) {
        hasCode(entity.getId(), entity.getBizDataId(), entity.getCode(), Boolean.FALSE);
        return baseMapper.insert(entity) > 0;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int updateImportConfig(MdsExcelImportConfig entity) {
        hasCode(entity.getId(), entity.getBizDataId(), entity.getCode(), Boolean.TRUE);
        return baseMapper.updateById(entity);
    }

    @Override
    public MdsExcelImportConfig getByCode(String code) {
        return baseMapper.selectOne(Wrappers.<MdsExcelImportConfig>lambdaQuery()
                .eq(MdsExcelImportConfig::getCode, code)
                .eq(MdsExcelImportConfig::getBeActive, Boolean.TRUE)
                .eq(MdsExcelImportConfig::getBeDeleted, Boolean.FALSE));
    }


    @Override
    public MdsExcelImportConfig getByDefaultConfig() {
        return baseMapper.selectOne(Wrappers.<MdsExcelImportConfig>lambdaQuery()
                .eq(MdsExcelImportConfig::getBeDefault, Boolean.TRUE)
                .eq(MdsExcelImportConfig::getBeActive, Boolean.TRUE)
                .eq(MdsExcelImportConfig::getBeDeleted, Boolean.FALSE));
    }

    @Override
    public MdsExcelImportConfig selectByCode(String code) {
        return baseMapper.selectOne(Wrappers.<MdsExcelImportConfig>lambdaQuery()
                .eq(MdsExcelImportConfig::getCode, code)
                .eq(MdsExcelImportConfig::getBeActive, Boolean.TRUE)
                .eq(MdsExcelImportConfig::getBeDeleted, Boolean.FALSE));
    }

    @Override
    public Object importExcel(DynamicExcelResult dynamicExcelResult) throws InvocationTargetException, IllegalAccessException {
        // 获取用户配置的服务类
        Object bean = SpringUtil.getBean(dynamicExcelResult.getConfigInfo().getBeanName());
        // 获取用户配置的执行方法
        Method[] methods = bean.getClass().getDeclaredMethods();

        Method serviceMethod = null;

        int excelRecordIndex = -1, bindingResultIndex = -1, serviceMethodCount = -1;

        for (Method method : methods) {
            excelRecordIndex = bindingResultIndex = -1;

            if (dynamicExcelResult.getConfigInfo().getMethodName().equals(method.getName())) {
                Class<?>[] parameterTypes = method.getParameterTypes();
                if (parameterTypes.length == 0) {
                    continue;
                }

                for (int i = 0; i < parameterTypes.length; i++) {
                    if (parameterTypes[i].isAssignableFrom(List.class)) {
                        excelRecordIndex = i;
                    }

                    if (parameterTypes[i].isAssignableFrom(BindingResult.class)) {
                        bindingResultIndex = i;
                    }
                }


                if ((excelRecordIndex > -1 && bindingResultIndex > -1) || excelRecordIndex > -1) {
                    serviceMethod = method;
                    serviceMethodCount = parameterTypes.length;
                    break;
                }

            }
        }

        Validate.isTrue(excelRecordIndex != -1, "Parameter 'noList' not found. Available parameters are [collection, list]");

        Object[] parameters = new Object[serviceMethodCount];
        for (int i = 0; i < serviceMethodCount; i++) {
            if (excelRecordIndex != -1 && i == excelRecordIndex) {
                parameters[i] = dynamicExcelResult;
                continue;
            }
            if (bindingResultIndex != -1 && i == bindingResultIndex) {
                parameters[i] = dynamicExcelResult.getBindingResult();
                continue;
            }
            parameters[i] = null;
        }

        // 执行调用并返回结果
        return serviceMethod.invoke(bean, parameters);
    }


    private void hasCode(String id, String bizDataId, String code, Boolean isUpdate) {
        QueryWrapper<MdsExcelImportConfig> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(MdsExcelImportConfig::getCode, code)
                .eq(MdsExcelImportConfig::getBizDataId, bizDataId);

        if (isUpdate) {
            queryWrapper.lambda().ne(MdsExcelImportConfig::getId, id);
        }

        Integer count = baseMapper.selectCount(queryWrapper);

        Validate.isTrue(count == 0, code + " already exists");
    }
}
